package com.springcloud.hystrixdemo.controller

import com.springcloud.hystrixdemo.service.FeignService
import com.springcloud.hystrixdemo.service.UserService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RestController

import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock

@RestController
class MyController {

    @Autowired
    UserService userService

    @Autowired
    FeignService feignService



    @GetMapping('/user/{name}')
    String get(@PathVariable String name)
    {
        //测试缓存
        50.times {
            userService.getUser(name)
        }
        userService.clear(name)

        //测试fallback
        userService.getUser(name)
    }


    @GetMapping('/test')
    def test()
    {

        List<Thread> threads=[]
            //为了测试Hystrix对并发访问的限流控制,这里开启20个线程模拟并发访问
            20.times {
                def t=new Thread(){
                    @Override
                    void run() {

                            userService.t(super)
                    }
                }
                t.name="测试线程:${it}"
                threads<<t
            }

            threads.each {
                sleep(20)
                it.start()
            }
            threads.each {
                it.join()
            }


        '执行结束'
    }

    @GetMapping('/msg/{wd}')
    String msg(@PathVariable String wd){

        //测试请求合并
        def list=[]
        5.times {
            sleep(10)
            list<<userService.collapse("${it}")
        }


        //测试fallback
        try {
            feignService.msg(wd)
        }
        catch (e){
            e.getMessage()
        }
    }



    //信号量原理
    static void main(String[] args) {
        LinkedBlockingQueue<Lock> locks=new LinkedBlockingQueue<>()

        //创建20个公平锁与队列中,每个锁就是一个信号量
        2.times {
            locks.put(new ReentrantLock(true))
        }


        100.times {
            sleep(20)
            new Thread() {

                @Override
                void run() {

                    //每个线程在进入直线首先从锁队列中获取锁
                    Lock lock=locks.take()
                    lock.lock()
                    //Groovy的this在匿名内部类中的含义与java不同.不可以使用this访问从父类继承来的属性
                    sleep(90)
                    println( "${super.name}" )

                    //使用完将锁放回,并释放锁
                    locks.put(lock)
                    lock.unlock()
                }

            }.start()
        }

    }

}
